package com.cykj.pos.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cykj.common.annotation.DataSource;
import com.cykj.common.config.RuoYiConfig;
import com.cykj.common.constant.Constants;
import com.cykj.common.core.domain.AjaxResult;
import com.cykj.common.core.domain.entity.SysUser;
import com.cykj.common.enums.DataSourceType;
import com.cykj.pos.domain.BizVerifyCode;
import com.cykj.pos.domain.dto.VerifyCodeDTO;
import com.cykj.pos.enums.bizstatus.BizStatusContantEnum;
import com.cykj.pos.mapper.BizVerifyCodeMapper;
import com.cykj.pos.service.IBizVerifyCodeService;
import com.cykj.pos.service.ISMSService;
import com.cykj.pos.util.DateUtils;
import com.cykj.pos.util.VerifyCodeUtils;
import com.cykj.system.service.ISysUserService;
import com.github.qcloudsms.SmsSingleSenderResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 短信验证码Service业务层处理
 *
 * @author ningbingwu
 * @date 2021-01-18
 */
@Service
@Slf4j
public class BizVerifyCodeServiceImpl extends ServiceImpl<BizVerifyCodeMapper, BizVerifyCode> implements IBizVerifyCodeService {

    @Autowired
    private ISMSService smsService;

    @Autowired
    private RuoYiConfig config;

    @Autowired
    private BizVerifyCodeMapper verifyCodeMapper;

    @Autowired
    private ISysUserService iSysUserService;

    @Override
    @DataSource(DataSourceType.SLAVE)
    public List<BizVerifyCode> queryList(BizVerifyCode bizVerifyCode) {
        LambdaQueryWrapper<BizVerifyCode> lqw = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(bizVerifyCode.getVerCode())){
            lqw.eq(BizVerifyCode::getVerCode ,bizVerifyCode.getVerCode());
        }
        if (bizVerifyCode.getVerStarttime() != null){
            lqw.eq(BizVerifyCode::getVerStarttime ,bizVerifyCode.getVerStarttime());
        }
        if (bizVerifyCode.getVerEndtime() != null){
            lqw.eq(BizVerifyCode::getVerEndtime ,bizVerifyCode.getVerEndtime());
        }
        if (bizVerifyCode.getVerStatus() != null){
            lqw.eq(BizVerifyCode::getVerStatus ,bizVerifyCode.getVerStatus());
        }
        if (StringUtils.isNotBlank(bizVerifyCode.getVerMobile())){
            lqw.eq(BizVerifyCode::getVerMobile ,bizVerifyCode.getVerMobile());
        }
        if (bizVerifyCode.getVerUserId() != null){
            lqw.eq(BizVerifyCode::getVerUserId ,bizVerifyCode.getVerUserId());
        }
        if (StringUtils.isNotBlank(bizVerifyCode.getVar1())){
            lqw.eq(BizVerifyCode::getVar1 ,bizVerifyCode.getVar1());
        }
        if (StringUtils.isNotBlank(bizVerifyCode.getVar2())){
            lqw.eq(BizVerifyCode::getVar2 ,bizVerifyCode.getVar2());
        }
        if (StringUtils.isNotBlank(bizVerifyCode.getVar3())){
            lqw.eq(BizVerifyCode::getVar3 ,bizVerifyCode.getVar3());
        }
        return this.list(lqw);
    }

    @Override
    @Transactional
    public BizStatusContantEnum sendVerifyCode(String mobile,Long userId){
        // 先验证验证码是否有效   如果再1分钟之内，不允许重复请求
        Integer minEffectiveDuration = config.getMinEffectiveDuration();
        // 获得和上一次短信验证码的时间的差值
        VerifyCodeDTO codeDTO = this.getMinEffectiveDurationMinute(mobile);
        if(codeDTO != null ){
            Long minute = codeDTO.getSecond();
            if(minute<minEffectiveDuration){
                // 已经获取验证码，请确认验证码
                return BizStatusContantEnum.SMS_EXIST_REQUIRED;
            }
        }
        String code = VerifyCodeUtils.getVerifyCode();
//        SmsSingleSenderResult result = smsService.sendVerifyCode(mobile,code,"partner register");
        SysUser sysUser = iSysUserService.selectUserById(userId);
        String result = smsService.sendMessage(code,mobile,sysUser.getDeptId());
        if("failureToSend".equals(result)) {
            return BizStatusContantEnum.SMS_TEMPLATE_NULL;// 未配置模板
        }else{
            JSONObject resStr = JSONObject.parseObject(result);
            if("success".equals(resStr.getString("status"))){
                BizVerifyCode verifyCode = new BizVerifyCode();
                verifyCode.setVerCode(code);
                verifyCode.setVerMobile(mobile);
                LocalDateTime localDateTime = LocalDateTime.now();
                String startTime = DateUtils.localeDateTime2String(localDateTime, Constants.DATETIME_FORMATTER);
                verifyCode.setVerStarttime(startTime);
                Integer smsEffectiveDuration = config.getSmsEffectiveDuration();
                LocalDateTime endLocalTime = localDateTime.plusMinutes(smsEffectiveDuration);
                String endTime = DateUtils.localeDateTime2String(endLocalTime, Constants.DATETIME_FORMATTER);
                verifyCode.setVerEndtime(endTime);
                verifyCode.setVerUserId(userId);
                verifyCode.setVar1(resStr.getString("send_id"));
                this.save(verifyCode);
                return BizStatusContantEnum.BIZ_SUCCESS;
            }else{
                return BizStatusContantEnum.SMS_FAIL;
            }

        }/*else if(result.result == 1023){
            return BizStatusContantEnum.SMS_FAIL_FREQUENCY;
        }*/
    }

    @Override
    public BizStatusContantEnum verifyCodeValidate(String mobile, String verifyCode){
        LambdaQueryWrapper<BizVerifyCode> lqw = Wrappers.lambdaQuery();
        lqw.eq(BizVerifyCode::getVerCode ,verifyCode);
        lqw.eq(BizVerifyCode::getVerStatus ,0);
        lqw.eq(BizVerifyCode::getVerMobile ,mobile);
        BizVerifyCode bizVerifyCode = this.getOne(lqw);
        if(bizVerifyCode == null){
            return BizStatusContantEnum.SMS_INVALIDATED;
        }
        String endTime = bizVerifyCode.getVerEndtime();
        LocalDateTime endLocalTime = DateUtils.stringToLocalDateTime(endTime, Constants.DATETIME_FORMATTER);
        if(endLocalTime.compareTo(LocalDateTime.now()) < 0){
            bizVerifyCode.setVerStatus(1);
            this.saveOrUpdate(bizVerifyCode);
            return BizStatusContantEnum.SMS_DURATION_EXPIRED;
        }
        bizVerifyCode.setVerStatus(1);
        this.saveOrUpdate(bizVerifyCode);
        return BizStatusContantEnum.SMS_SUCCESS;
    }

    @Override
    @DataSource(DataSourceType.SLAVE)
    public VerifyCodeDTO getMinEffectiveDurationMinute(String mobile) {
        return verifyCodeMapper.getMinEffectiveDurationMinute(mobile);
    }

    @Override
    @Transactional
    public AjaxResult sendVerifyCodeWeChat(String mobile) {
        // 先验证验证码是否有效   如果再1分钟之内，不允许重复请求
        Integer minEffectiveDuration = config.getMinEffectiveDuration();
        // 获得和上一次短信验证码的时间的差值
        VerifyCodeDTO codeDTO = this.getMinEffectiveDurationMinute(mobile);
        if (codeDTO != null) {
            Long minute = codeDTO.getSecond();
            if (minute < minEffectiveDuration) {
                // 已经获取验证码，请确认验证码
                return AjaxResult.error("已经获取验证码，请确认验证码");
            }
        }
        String code = VerifyCodeUtils.getVerifyCode();
        SmsSingleSenderResult result = smsService.sendVerifyCode(mobile, code, "partner register");
//        SmsSingleSenderResult result = new SmsSingleSenderResult();
//        result.result = 0;
//        result.sid = "2433:320682672116430258889697346";
        if (result != null && result.result == 0) {
            BizVerifyCode verifyCode = new BizVerifyCode();
            verifyCode.setVerCode(code);
            verifyCode.setVerMobile(mobile);

            LocalDateTime localDateTime = LocalDateTime.now();
            String startTime = DateUtils.localeDateTime2String(localDateTime, Constants.DATETIME_FORMATTER);
            verifyCode.setVerStarttime(startTime);

            Integer smsEffectiveDuration = config.getSmsEffectiveDuration();
            LocalDateTime endLocalTime = localDateTime.plusMinutes(smsEffectiveDuration);
            String endTime = DateUtils.localeDateTime2String(endLocalTime, Constants.DATETIME_FORMATTER);
            verifyCode.setVerEndtime(endTime);

            verifyCode.setVar1(result.sid);
            this.save(verifyCode);
            return AjaxResult.success("业务操作成功", code);
        } else if (result.result == 1023) {
            return AjaxResult.error("短信验证码发送过于频繁");
        }
        return AjaxResult.error("短信验证码发送失败");
    }

}
